//*** Guidance generated code ***//
using System;
using System.Collections.Generic;

using System.Linq;
using System.Xml.Linq;

using ProjectBase.Core;
using ProjectBase.Data;
using ProjectBase.Data.Xml;

using $prjsn$.Common;
using $prjsn$.Common.Data.Services;
using $prjsn$.Entity.Services;

namespace $safeprojectname$.Services.Xml
{
    public class UserDao : BaseXmlDao<User, int, UserFilter>, IUserDao
    {
        #region Find
        /// <summary>
        ///     Fills the Criteria list with where statements based on provided filter
        /// </summary>
        /// <param name = "filter"></param>
        /// <returns></returns>
        public override IEnumerable<User> Find(UserFilter filter)
        {
            // Equal
            Criteria.Add(entity => entity.ID.IsEqual(filter.IdExact));
            Criteria.Add(entity => entity.Login.IsExact(filter.LoginExact));

            // Like
            Criteria.Add(entity => entity.Login.IsLike(filter.Login));
            Criteria.Add(entity => entity.FirstName.IsLike(filter.FirstName));
            Criteria.Add(entity => entity.LastName.IsLike(filter.LastName));
            Criteria.Add(entity => entity.CurrentRole.IsLike(filter.RoleSearch));
            return GetListByCriteria(filter);
        }
        #endregion Find

        #region GetAll
        public virtual IEnumerable<User> GetAll()
        {
            return Find(new UserFilter { TakeRows = int.MaxValue });
        }
        #endregion GetAll

        #region XML - ENTITY mapping
        /// <summary>
        ///     Converts the XElement into the User
        /// </summary>
        /// <param name = "element"></param>
        /// <returns></returns>
        protected override User CreateEntity(XElement element)
        {
            var entity = FillEntity(new User(), element); // base converts ValueTypes and String

            // load roles
            var roles = element.Elements(Str.Business.Services.Role);
            if (roles.Is())
            {
                foreach (var role in roles)
                {
                    if (role.Attribute(Str.Business.Services.Name).Is())
                    {
                        entity.Roles.Add(role.Attribute(Str.Business.Services.Name).Value);
                    }
                }
            }

            // select current one
            var currentRole = element.Attribute(Str.Business.Services.CurrentRole);
            if (currentRole.Is()
                && entity.Roles.Contains(currentRole.Value))
            {
                entity.CurrentRole = currentRole.Value;
            }

            entity.SetId((int)element.Attribute(Str.Common.ID));
            return entity;
        }

        /// <summary>
        ///     Converts the User instnace into the XElement
        /// </summary>
        /// <param name = "entity"></param>
        /// <returns></returns>
        protected override XElement CreateElement(User entity)
        {
            var element = base.CreateElement(entity); // base converts ValueTypes and String

            // Roles list
            foreach (var role in entity.Roles)
            {
                var roleElement = new XElement(Str.Business.Services.Role);
                roleElement.Add(new XAttribute(Str.Business.Services.Name, role));
                element.Add(roleElement);
            }
            return element;
        }
        #endregion XML - ENTITY mapping

        #region NextId
        /// <summary>
        ///     Incremented 'Next ID' generator.
        ///     Searches for the max existing used value
        ///     and returnes that + 1
        /// </summary>
        /// <returns></returns>
        protected override int GetNextId(User entity = null)
        {
            var id = 0; // in case there is no element yet
            if (TheList.Any()) // element(s) exist(s) - find the largest ID
            {
                id = TheList.Max<User, int>(e => e.ID);
            }
            return ++id;
        }
        #endregion NextId
    }
}